Add gdk_window_restack
authorAlexander Larsson <alexl@redhat.com>
Wed, 2 Sep 2009 21:38:55 +0000 (23:38 +0200)
committerAlexander Larsson <alexl@redhat.com>
Wed, 2 Sep 2009 21:38:55 +0000 (23:38 +0200)
This lets you restack a window above or below a specified sibling.
At least eclipse wants this functionallity.

gdk/gdk.symbols
gdk/gdkwindow.c
gdk/gdkwindow.h
gdk/gdkwindowimpl.h
gdk/quartz/gdkwindow-quartz.c
gdk/win32/gdkwindow-win32.c
gdk/x11/gdkwindow-x11.c

index 7956390d25a61f138fb1ef6d71f4f2947ec6cbd6..e8c51093b23d3e4028e7b54a6daf5b653abe2f05 100644 (file)
@@ -651,6 +651,7 @@ gdk_window_get_events
 gdk_window_set_events
 gdk_window_raise
 gdk_window_lower
+gdk_window_restack
 gdk_window_move
 gdk_window_resize
 gdk_window_move_resize
index f9fb2adccc9c9a03fcf1b30e83ec7af1c3253d85..bc0a5057d955a682d9f7df41e37b444564a891e6 100644 (file)
@@ -6448,6 +6448,122 @@ gdk_window_lower (GdkWindow *window)
   gdk_window_invalidate_in_parent (private);
 }
 
+/**
+ * gdk_window_restack:
+ * @window: a #GdkWindow
+ * @sibling: a #GdkWindow that is a sibling of @window, or %NULL
+ * @above: a boolean
+ *
+ * Changes the position of  @window in the Z-order (stacking order), so that
+ * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is
+ * %FALSE).
+ *
+ * If @sibling is %NULL, then this either raises (if @above is %TRUE) or
+ * lowers the window.
+ *
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_window_restack() only
+ * requests the restack, does not guarantee it.
+ *
+ * Since: 2.18
+ */
+void
+gdk_window_restack (GdkWindow     *window,
+                   GdkWindow     *sibling,
+                   gboolean       above)
+{
+  GdkWindowObject *private;
+  GdkWindowImplIface *impl_iface;
+  GdkWindowObject *parent;
+  GdkWindowObject *above_native;
+  GList *sibling_link;
+  GList *native_children;
+  GList *l, listhead;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (sibling == NULL || GDK_IS_WINDOW (sibling));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  if (sibling == NULL)
+    {
+      if (above)
+       gdk_window_raise (window);
+      else
+       gdk_window_lower (window);
+      return;
+    }
+
+  if (gdk_window_is_toplevel (private))
+    {
+      g_return_if_fail (gdk_window_is_toplevel (sibling));
+      impl_iface->restack_toplevel (window, sibling, above);
+      return;
+    }
+
+  parent = private->parent;
+  if (parent)
+    {
+      sibling_link = g_list_find (parent->children, sibling);
+      g_return_if_fail (sibling_link != NULL);
+      if (sibling_link == NULL)
+       return;
+
+      parent->children = g_list_remove (parent->children, window);
+      if (above)
+       parent->children = g_list_insert_before (parent->children,
+                                                sibling_link,
+                                                window);
+      else
+       parent->children = g_list_insert_before (parent->children,
+                                                sibling_link->next,
+                                                window);
+
+      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+      if (gdk_window_has_impl (private))
+       {
+         above_native = find_native_sibling_above (parent, private);
+         if (above_native)
+           {
+             listhead.data = window;
+             listhead.next = NULL;
+             listhead.prev = NULL;
+             impl_iface->restack_under ((GdkWindow *)above_native, &listhead);
+           }
+         else
+           impl_iface->raise (window);
+       }
+      else
+       {
+         native_children = NULL;
+         get_all_native_children (private, &native_children);
+         if (native_children != NULL)
+           {
+             above_native = find_native_sibling_above (parent, private);
+             if (above_native)
+               impl_iface->restack_under ((GdkWindow *)above_native,
+                                          native_children);
+             else
+               {
+                 /* Right order, since native_children is bottom-topmost first */
+                 for (l = native_children; l != NULL; l = l->next)
+                   impl_iface->raise (l->data);
+               }
+
+             g_list_free (native_children);
+           }
+       }
+    }
+
+  recompute_visible_regions (private, TRUE, FALSE);
+
+  _gdk_synthesize_crossing_events_for_geometry_change (window);
+  gdk_window_invalidate_in_parent (private);
+}
+
+
 /**
  * gdk_window_show:
  * @window: a #GdkWindow
index a3297d24ad7cf34cfe357afe49ae712ee5513c59..bea3ca9789004646055852d333574a642291f85f 100644 (file)
@@ -364,6 +364,9 @@ void          gdk_window_clear_area_e          (GdkWindow     *window,
                                                 gint           height);
 void          gdk_window_raise                 (GdkWindow     *window);
 void          gdk_window_lower                 (GdkWindow     *window);
+void          gdk_window_restack               (GdkWindow     *window,
+                                               GdkWindow     *sibling,
+                                               gboolean       above);
 void          gdk_window_focus                 (GdkWindow     *window,
                                                 guint32        timestamp);
 void          gdk_window_set_user_data         (GdkWindow     *window,
index b8de4744d1b15a4865e18343a0f6696f6bebd262..00f2f1b13da7453ed433a7325b2fa51f680e2521 100644 (file)
@@ -51,6 +51,9 @@ struct _GdkWindowImplIface
   void         (* lower)                (GdkWindow       *window);
   void         (* restack_under)        (GdkWindow       *window,
                                         GList           *native_siblings);
+  void         (* restack_toplevel)     (GdkWindow       *window,
+                                        GdkWindow       *sibling,
+                                        gboolean        above);
 
   void         (* move_resize)          (GdkWindow       *window,
                                          gboolean         with_move,
index 43f93f9b5c5a4f3312f42108ead98410a4e01f0f..6b8373b2b9539535f9dc5602c9815517caa16cda 100644 (file)
@@ -1541,6 +1541,14 @@ gdk_window_quartz_lower (GdkWindow *window)
     }
 }
 
+static void
+gdk_window_quartz_restack_toplevel (GdkWindow *window,
+                                   GdkWindow *sibling,
+                                   gboolean   above)
+{
+  /* FIXME: Implement this */
+}
+
 static void
 gdk_window_quartz_set_background (GdkWindow      *window,
                                   const GdkColor *color)
@@ -2907,6 +2915,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->get_events = gdk_window_quartz_get_events;
   iface->raise = gdk_window_quartz_raise;
   iface->lower = gdk_window_quartz_lower;
+  iface->restack_toplevel = gdk_window_quartz_restack_toplevel;
   iface->move_resize = gdk_window_quartz_move_resize;
   iface->set_background = gdk_window_quartz_set_background;
   iface->set_back_pixmap = gdk_window_quartz_set_back_pixmap;
index a849e260a8f59c1b27fd109503b1f16c53bec5f8..c94563165cd97bd5cbb5fd6c1659182f99515623 100644 (file)
@@ -2092,6 +2092,14 @@ gdk_win32_window_restack_under (GdkWindow *window,
        // ### TODO
 }
 
+static void
+gdk_win32_window_restack_toplevel (GdkWindow *window,
+                                  GdkWindow *sibling,
+                                  gboolean   above)
+{
+       // ### TODO
+}
+
 void
 gdk_window_get_root_origin (GdkWindow *window,
                            gint      *x,
@@ -3634,6 +3642,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->raise = gdk_win32_window_raise;
   iface->lower = gdk_win32_window_lower;
   iface->restack_under = gdk_win32_window_restack_under;
+  iface->restack_toplevel = gdk_win32_window_restack_toplevel;
   iface->move_resize = gdk_win32_window_move_resize;
   iface->set_background = gdk_win32_window_set_background;
   iface->set_back_pixmap = gdk_win32_window_set_back_pixmap;
index 1682151bb1f4095895ed65a1e99b8771249fea35..82ce21333623cf3440298c33be6562e942a64d16 100644 (file)
@@ -1715,6 +1715,21 @@ gdk_window_x11_restack_under (GdkWindow *window,
   g_free (windows);
 }
 
+static void
+gdk_window_x11_restack_toplevel (GdkWindow *window,
+                                GdkWindow *sibling,
+                                gboolean   above)
+{
+  XWindowChanges changes;
+
+  changes.sibling = GDK_WINDOW_XID (sibling);
+  changes.stack_mode = above ? Above : Below;
+  XReconfigureWMWindow (GDK_WINDOW_XDISPLAY (window),
+                       GDK_WINDOW_XID (window),
+                       GDK_WINDOW_SCREEN (window),
+                       CWStackMode | CWSibling, &changes);
+}
+
 static void
 gdk_window_x11_lower (GdkWindow *window)
 {
@@ -5562,6 +5577,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->raise = gdk_window_x11_raise;
   iface->lower = gdk_window_x11_lower;
   iface->restack_under = gdk_window_x11_restack_under;
+  iface->restack_toplevel = gdk_window_x11_restack_toplevel;
   iface->move_resize = gdk_window_x11_move_resize;
   iface->set_background = gdk_window_x11_set_background;
   iface->set_back_pixmap = gdk_window_x11_set_back_pixmap;